import { ref } from 'vue'
import {
  NumOrStr,
  NumsOrStrs,
  Option,
  SelectedResult,
  TabItem,
  TabListType,
  UseMutexResult,
} from '../types'

export default function useMutex(data: TabListType, initSelectList: TabListType | undefined = undefined): UseMutexResult {
  
  const mutexList = ref<TabListType>(data);
  const selectedList = ref<TabListType>(initSelectList ?? []);

  const handleSelect = (item: TabItem): SelectedResult => {
    if (item.lock) {
      return [false, false]
    }
    return updateData(item)
  };

  const judgeActived = (item: TabItem) => {
    const result = selectedList.value.find((i) => i.id === item.id);
    return !!result;
  };

  const updateData = (currentItem: TabItem) => {
    const status = judgeActived(currentItem)
    
    if (status) {
      // 不激活
      // 如果是单选，则同类只剩下一项，直接返回
      if(!currentItem.multiple) {
        return [true, true]
      }
      removeTabItem(currentItem)
    } else {
      // 激活
      // 如果是单选，激活一项则要把相同类型的给干掉
      if(!currentItem.multiple) {
        const sameCategoryList = selectedList.value.filter((i) => i.category === currentItem.category)
        sameCategoryList.forEach((item) => {
          removeTabItem(item)
        })
      }
      addTabItem(currentItem)
    }

    return [true, !status]
  }

  const addTabItem = (currentItem: TabItem) => {
    const options: Option = {
      currentItem,
      oldMutexList: mutexList.value,
      selectedList: [...selectedList.value],
    };
    selectedList.value.push(currentItem);
    mutexList.value = updateLockStatus(true, options);
  }

  const removeTabItem = (currentItem: TabItem) => {
    selectedList.value = selectedList.value.filter((i) => i.id !== currentItem.id);

    const options: Option = {
      currentItem,
      oldMutexList: mutexList.value,
      selectedList: [...selectedList.value],
    };
    mutexList.value = updateLockStatus(false, options);
  }

  return {
    mutexList,
    selectedList,
    handleSelect,
    judgeActived,
  };
}

function updateLockStatus(flag: boolean, options: Option) {
  const { currentItem, oldMutexList, selectedList } = options;
  const list: TabListType = [];
  const needChangeStatusIds = getNeedChangeStatusIds(
    currentItem.oppositeIds,
    selectedList
  );

  oldMutexList.forEach((item: TabItem) => {
    const lock = needChangeStatusIds.includes(item.id) ? flag : !!item.lock;
    list.push({
      ...item,
      lock,
    });
  });

  return list;
}

function getNeedChangeStatusIds(oppositeIds: NumsOrStrs, selectedList: TabListType) {
  const ids: NumsOrStrs = [];
  const allSelectedOppositeIds = getAllSelectedOppositeIds(selectedList);

  oppositeIds.forEach((id: NumOrStr) => {
    if (!allSelectedOppositeIds.includes(id)) {
      ids.push(id);
    }
  });

  return ids;
}

function getAllSelectedOppositeIds(list: TabListType) {
  let ids: NumsOrStrs = [];

  list.forEach((item: TabItem) => {
    ids.push(...item.oppositeIds);
  });
  ids = [...new Set<NumOrStr>(ids)];

  return ids;
}
